/*
 * @Author: xiaosihan
 * @Date: 2024-06-17 02:15:58
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-06-18 20:34:38
 */

import { BufferGeometry, Camera, Clock, Color, Group, Material, NormalBufferAttributes, Object3DEventMap, PerspectiveCamera, Points, Scene, Vector2, WebGLRenderer } from "three";
import FireGromtry from "./FireGromtry";
import FireMaterial from "./FireMaterial";
import { degToRad } from "three/src/math/MathUtils";

// 粒子火焰效果
export default class Fire extends Points {

    constructor() {
        super();
    }

    geometry = new FireGromtry(0, 0, 0);

    material = new FireMaterial();

    // 火焰的颜色
    fireColor = "#ff2200";
    // 火焰的整体缩放值
    fireScale = 1;
    // 火焰的燃烧半径
    fireRadius = 0.5;
    // 火焰的高度
    fireHeight = 3;
    // 火焰的粒子数量
    particleCount = 500;
    // 是否是透视相机
    isPerspectiveCamera = true;
    //渲染器的尺寸
    size = new Vector2();

    // 缓存的参数
    cacheProps = {
        fireColor: "#ff2200",
        fireScale: 0,
        fireRadius: 0.5,
        fireHeight: 3,
        particleCount: 500,
        width: 0,
        height: 0,
        isPerspectiveCamera: true
    }

    // 当前渲染的帧数
    updataFrame = 0;

    // 时钟对象
    clock = new Clock();

    onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry<NormalBufferAttributes>, material: Material, group: Group<Object3DEventMap>): void {

        const delta = this.clock.getDelta();
        renderer.getSize(this.size);

        if (
            this.cacheProps.fireColor !== this.fireColor ||
            this.cacheProps.fireScale !== this.fireScale ||
            this.cacheProps.fireRadius !== this.fireRadius ||
            this.cacheProps.fireHeight !== this.fireHeight ||
            this.cacheProps.particleCount !== this.particleCount ||
            this.cacheProps.isPerspectiveCamera !== this.isPerspectiveCamera ||
            this.cacheProps.width !== this.size.x ||
            this.cacheProps.height !== this.size.y
        ) {
            this.cacheProps.fireColor = this.fireColor;
            this.cacheProps.fireScale = this.fireScale;
            this.cacheProps.fireRadius = this.fireRadius;
            this.cacheProps.fireHeight = this.fireHeight;
            this.cacheProps.particleCount = this.particleCount;
            this.cacheProps.isPerspectiveCamera = this.isPerspectiveCamera;
            this.cacheProps.width = this.size.x;
            this.cacheProps.height = this.size.y;

            this.geometry = new FireGromtry(this.fireRadius * this.fireScale, this.fireHeight * this.fireScale, this.particleCount);

            this.material.uniforms.color.value = new Color(this.fireColor);
            this.material.uniforms.size.value = this.fireScale * 0.4;
            if ((camera as PerspectiveCamera).isPerspectiveCamera) {
                this.material.uniforms.heightOfNearPlane.value = Math.abs(this.size.y / (2 * Math.tan(degToRad((camera as PerspectiveCamera).fov * 0.5))));
            } else {
                this.material.uniforms.heightOfNearPlane.value = 0;
            }

        }

        this.isPerspectiveCamera = (camera as PerspectiveCamera).isPerspectiveCamera;

        this.material.uniforms.time.value = (this.material.uniforms.time.value + delta) % 1;

    }

}